package cn.itsource.pay.controller;

import cn.itsource.order.domain.OrderAdopt;
import cn.itsource.order.mapper.OrderAdoptMapper;
import cn.itsource.order.service.IOrderAdoptService;
import cn.itsource.pay.domain.PayDto;
import cn.itsource.pay.domain.TPayAlipayInfo;
import cn.itsource.pay.other.AlipayConfig;
import cn.itsource.pay.service.impl.AlipayInfoServiceImpl;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Controller
@RequestMapping("/pay")
public class PayController {

    @Autowired
    private AlipayInfoServiceImpl alipayInfoService;

    @Autowired
    private OrderAdoptMapper orderAdoptMapper;

    /**
     * 这个方法，用于前端点击“提交订单”，生成并跳转到支付宝的 带二维码的支付界面
     *
     * @param dto
     * @return
     */
    @PostMapping("/gobuy")
    @ResponseBody
    public String goBuy(@RequestBody PayDto dto) {
        return alipayInfoService.goBuy(dto);
    }

//    //用户支付订单完成后，就会同步回调当前请求
//    @GetMapping("/returnUrl")
//    public String returnUrl(String out_trade_no, String total_amount, String trade_no) {
//        System.out.println(">>asdfasdfasdfasdfUrl>>>>>>>>>>>" + out_trade_no + "," + total_amount + "," + trade_no);
//        System.out.println(">>>>>>>>>returnUrl>>>>>>>>>>>" + out_trade_no + "," + total_amount + "," + trade_no);
//        System.out.println(">>>>>>>>>returnUrl>021年10月29>>" + out_trade_no + "," + total_amount + "," + trade_no);
//        return null;
//    }


    /**
     * 真实环境中，会使用这种方式进行操作。
     *  特点：比returnUrl更安全
     * 异步请求：默认情况下，只要触发了设置的回调URL，
     * 则说明，此次用户支付的操作：tradeStatus.TRADE_SUCCESS	支付成功	1
     * 【离线付】
     *
     * ---------------------- 注意事项：
     * 内网穿透：让你眼前这台电脑拥有一个外网可以调用的ip地址
     * 在使用这个notify的回调地址，需要注意如下几点：
     *      1. 需要在支付宝开放平台中，配置回调地址
     *                  这个回调必须可以  外网访问 （如果是本地测试，需要使用内网穿透工具）
     *                          穿透工具： natapp 或  花生壳
     *
     *      2. 在代码中，发起支付请求时，配置的notifyurl参数，必须与 控制台配置的回调地址一样
     *
     * @return
     */
    @RequestMapping("/notifyUrl")
    public String notifyUrl(HttpServletRequest request) {
        System.out.println(">>>>>>>>>notifyUrl>>>>>>>");

        try {
            //获取支付宝POST过来反馈信息(返回的结果非常的多，需要程序自行解析)
            Map<String, String> params = new HashMap<String, String>();
            Map<String, String[]> requestParams = request.getParameterMap();
            //1. 将回调请求中，携带的参数，进行转换，全部转为 HashMap<String,String>的格式
            for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
                String name = (String) iter.next();
                String[] values = (String[]) requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }
                params.put(name, valueStr);
            }

            //2. 转换之后，注意：有1个核心返回值：trade_status ---->值为 TRADE_SUCCESS 说明 ，支付成功
            //获取appid
            String app_id = params.get("app_id");
            //获取支付信息对象
            TPayAlipayInfo alipayInfo = alipayInfoService.loadByAppid(app_id);
            //主要用于校验
            boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayInfo.getAlipayPublicKey(), AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名

            //——请在这里编写您的程序（以下代码仅作参考）——

            /* 实际验证过程建议商户务必添加以下校验：
            1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
            2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
            3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
            4、验证app_id是否为该商户本身。
            */
            if (signVerified) {//验证成功
                //商户订单号
                String out_trade_no = request.getParameter("out_trade_no");
                //支付宝交易号（这个参数，是支付宝方支付成功后，生成的一个支付交易单号。主要用于：对帐）
                String trade_no = request.getParameter("trade_no");
                //交易状态
                String trade_status = request.getParameter("trade_status");
                //交易成功
                if (trade_status.equals("TRADE_SUCCESS")) {
                    //这里将是处理支付成功之后的，业务逻辑
                    // TODO: 2022/3/8  这里就应该查询订单信息,改变订单状态
                    //1.根据订单号查询到订单
                    OrderAdopt orderAdopt = orderAdoptMapper.findByOrderSn(out_trade_no);

                    //2.保存支付宝流水号，支付时间，支付状态
                    orderAdopt.setState(1);//已完成
                    orderAdopt.setLastPayTime(new Date());
                    orderAdopt.setPaySn(trade_no);

                    orderAdoptMapper.updateByPrimaryKey(orderAdopt);

                    //todo 宠物表要改成已售

                    return "success";
                }
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return "failure";
    }


    /**
     * 同步请求
     * 没有处理和数据库相关的业务的
     * @return
     */
    @RequestMapping("/returnUrl")
    public String returnUrl(HttpServletRequest request) {
        try {
            //获取支付宝GET过来反馈信息
            Map<String, String> params = new HashMap<String, String>();
            //把支付宝传递的参数封装为一个map集合
            Map<String, String[]> requestParams = request.getParameterMap();//{hobby:[java,c],name:"王天霸"}
            //循环迭代map
            for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
                //获取map的key值
                String name = (String) iter.next();
                //通过key获取对应的值
                String[] values = (String[]) requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }

                params.put(name, valueStr);//{hobby:"java,c", name:"王天霸"}
            }
            //获取appid
            String app_id = params.get("app_id");
            //获取支付信息对象
            TPayAlipayInfo alipayInfo = alipayInfoService.loadByAppid(app_id);

            //验签(校验数据在传输过程中，是否被破环，如果被破坏，验签失败，如果数据没有被破环，验签成功)
            boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayInfo.getAlipayPublicKey(), AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名
            //——请在这里编写您的程序（以下代码仅作参考）——
            if (signVerified) {
                //跳转到成功界面
                return "redirect:http://localhost:8081/success.html";
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return "redirect:http://localhost:8081/error.html";
    }
}
